﻿using System;

namespace Socium.Science {
	struct Vector {
		public readonly double X;
		public readonly double Y;

		public Vector(double x, double y) {
			X = x;
			Y = y;
		}

		public static Vector Origin {
			get { return new Vector(0d, 0d); }
		}

		public double Length {
			get { return (X.Square() + Y.Square()).Sqrt(); }
		}

		public Vector Perpendicular() {
			return new Vector(-Y, X);
		}

		public Vector Normalize() {
			var length = Length;
			if (length.IsZero()) {
				throw new InvalidOperationException("Attempt to normalize zero-length vector");
			}

			return new Vector(X / length, Y / length);
		}

		public Vector Rotate(double angle) {
			return new Vector(X*angle.Cos() - Y*angle.Sin(), X*angle.Sin() + Y*angle.Cos());
		}

		#region Operators

		public static Vector operator-(Vector value) {
			return new Vector(-value.X, -value.Y);
		}

		public static Vector operator+(Vector left, Vector right) {
			return new Vector(left.X + right.X, left.Y + right.Y);
		}

		public static Vector operator-(Vector left, Vector right) {
			return new Vector(left.X - right.X, left.Y - right.Y);
		}

		public static double operator*(Vector left, Vector right) {
			return left.X*right.X + left.Y*right.Y;
		}

		public static Vector operator*(Vector left, double right) {
			return new Vector(left.X * right, left.Y * right);
		}

		public static Vector operator/(Vector left, double right) {
			if (right.IsZero()) {
				throw new ArgumentException();
			}

			return new Vector(left.X / right, left.Y / right);
		}

		#endregion

		public override string ToString() {
			return string.Format("({0}, {1})", X, Y);
		}
	}
}
